package org.jianfa.rpc.server.thread;

import org.apache.zookeeper.data.Stat;
import org.jianfa.learn.common.zookeeper.ZookeeperRegistryCenter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.atomic.AtomicBoolean;

public class RecordResponseTimeThread extends Thread{

    private static final Logger logger = LoggerFactory.getLogger(RecordResponseTimeThread.class);

    private ZookeeperRegistryCenter zookeeperRegistryCenter;
    private String host;
    private String serverPath;
    private Object sigLock;
    private AtomicBoolean halt;
    private boolean paused;

    public RecordResponseTimeThread(ZookeeperRegistryCenter zookeeperRegistryCenter,
                                    String host) {
        this.zookeeperRegistryCenter = zookeeperRegistryCenter;
        this.host = host;
        this.serverPath = host;

        this.sigLock = new Object();
        this.halt = new AtomicBoolean(false);
        //一开始该线程不检查响应时间，响应时间为0
        //等到接受到第一个请求之后，
        this.paused = true;
    }

    public void togglePause(boolean paused) {
        synchronized (sigLock) {
            this.paused = paused;
            this.sigLock.notifyAll();
        }
    }

    public void halt() {
        synchronized (sigLock) {
            this.halt.compareAndSet(false, true);
            this.sigLock.notifyAll();
        }

        boolean interrupted = false;
        try {
            while (true) {
                try {
                    join();
                    break;
                } catch (InterruptedException ie) {
                    interrupted = true;
                }
            }
        } finally {
            if (interrupted) {
                Thread.currentThread().interrupt();
            }
        }
    }

    public void signalSchedulingChange() {
        synchronized (sigLock) {
            sigLock.notifyAll();
        }
    }

    @Override
    public void run() {
        try {
            while (!halt.get()) {

                synchronized (sigLock) {
                    for (;!halt.get() && paused;) {
                        synchronized (sigLock) {
                            logger.info("服务器还未收到任何请求，暂不检查响应时间。进入睡眠。睡眠时间为{}ms。", 10000);
                            sigLock.wait(10000);
                        }
                    }

                    if(halt.get()) {
                        break;
                    }
                }

                //开始检查响应时间
                String oldResponseTime = this.zookeeperRegistryCenter.getDirectly(serverPath);
                logger.info("检查服务器{}目前的响应时间是{}", serverPath, oldResponseTime);

                //分两种情况，
                //一种是检查到响应时间为0的。
                //检查到响应时间为0，不做任务操作。
                //然后就一直睡眠。
                if ("-1".equals(oldResponseTime)) {
                    synchronized (sigLock) {
                        logger.info("响应时间为-1。进入睡眠。");
                        sigLock.wait();
                    }
                }

                //一种是检查到响应时间不为0的。
                //如果（现在的时间 - 节点最后的更新时间）大于5，那么把响应时间更改为0。
                else {

                    Stat stat = this.zookeeperRegistryCenter.getStatDirectly(serverPath);
                    long lastModityTime = stat.getMtime();
                    long currentTime = System.currentTimeMillis(); //毫秒
                    long diff = currentTime - lastModityTime;
                    logger.info("响应时间到目前已经过了{}ms。", diff);
                    if (diff >= 5000) {
                        //
                        logger.info("响应时间到目前已经超过5秒了，响应时间失效。", diff);
                        this.zookeeperRegistryCenter.update(serverPath, "-1");
                    }

                    //如果（现在的时间 - 节点最后的更新时间）小于5秒
                    //那么先睡眠，一会儿再继续检查
                    else {
                        long left = (5000 - diff);
                        logger.info("响应时间到目前还未超过5秒。进入睡眠。睡眠时间为{}ms。", left);
                        synchronized (sigLock) {
                            sigLock.wait(left);
                        }
                    }
                }
            }
        } catch (Exception ex) {
            //异常
            logger.error("检查服务器响应时间发生异常", ex);
        }
    }
}
